﻿using Extented.UI.Core.Utils;

namespace System.Windows
{
    public static class RectExtension
    {
        public static MathLine TopLine(this Rect rect)
        {
            return new MathLine(0, 1, -rect.Top);
        }

        public static MathLine BottomLine(this Rect rect)
        {
            return new MathLine(0, 1, -rect.Bottom);
        }

        public static MathLine LeftLine(this Rect rect)
        {
            return new MathLine(1, 0, -rect.Left);
        }

        public static MathLine RightLine(this Rect rect)
        {
            return new MathLine(1, 0, -rect.Right);
        }

        public static RectCorner NearestCorner(this Rect rect, Point point)
        {
            double[] distances = {
									 point.Distance(rect.TopLeft()),
									 point.Distance(rect.TopRight()),
									 point.Distance(rect.BottomRight()),
									 point.Distance(rect.BottomLeft())
								 };
            double minDistance = distances[0];
            RectCorner nearestCorner = RectCorner.TopLeft;
            for (int i = 0; i < 4; i++)
            {
                if (distances[i] < minDistance)
                {
                    minDistance = distances[i];
                    nearestCorner = (RectCorner)i;
                }
            }
            return nearestCorner;
        }

        public static Point Corner(this Rect rect, RectCorner corner)
        {
            switch (corner)
            {
                case RectCorner.TopLeft: return rect.TopLeft();
                case RectCorner.TopRight: return rect.TopRight();
                case RectCorner.BottomRight: return rect.BottomRight();
                default: return rect.BottomLeft();
            }
        }

        public static Point KeyPoint(this Rect rect, RectKeyPoint keyPoint)
        {
            switch (keyPoint)
            {
                case RectKeyPoint.TopLeft: return rect.Corner(RectCorner.TopLeft);
                case RectKeyPoint.TopMiddle: return rect.TopMiddle();
                case RectKeyPoint.TopRight: return rect.Corner(RectCorner.TopRight);
                case RectKeyPoint.RightMiddle: return rect.RightMiddle();
                case RectKeyPoint.BottomRight: return rect.Corner(RectCorner.BottomRight);
                case RectKeyPoint.BottomMiddle: return rect.BottomMiddle();
                case RectKeyPoint.BottomLeft: return rect.Corner(RectCorner.BottomLeft);
                default: return rect.LeftMiddle();
            }
        }

        public static double CenterX(this Rect rect)
        {
            return rect.Left + rect.Width / 2;
        }

        public static double CenterY(this Rect rect)
        {
            return rect.Top + rect.Height / 2;
        }

        public static Point Center(this Rect rect)
        {
            return new Point(rect.CenterX(), rect.CenterY());
        }

        public static Point TopMiddle(this Rect rect)
        {
            return new Point(rect.CenterX(), rect.Top);
        }

        public static Point BottomMiddle(this Rect rect)
        {
            return new Point(rect.CenterX(), rect.Bottom);
        }

        public static Point LeftMiddle(this Rect rect)
        {
            return new Point(rect.Left, rect.CenterY());
        }

        public static Point RightMiddle(this Rect rect)
        {
            return new Point(rect.Right, rect.CenterY());
        }

        public static bool IsInRange(double x, double min, double max)
        {
            return x >= min && x <= max;
        }

        public static bool IsXInRange(this Rect rect, Point point)
        {
            return IsInRange(point.X, rect.Left, rect.Right);
        }

        public static bool IsYInRange(this Rect rect, Point point)
        {
            return IsInRange(point.Y, rect.Top, rect.Bottom);
        }

        public static bool IsInside(this Rect rect, Point point)
        {
            return IsXInRange(rect, point) && IsYInRange(rect, point);
        }

        public static Point TopLeft(this Rect rect)
        {
            return new Point(rect.Left, rect.Top);
        }

        public static Point TopRight(this Rect rect)
        {
            return new Point(rect.Right, rect.Top);
        }

        public static Point BottomRight(this Rect rect)
        {
            return new Point(rect.Right, rect.Bottom);
        }

        public static Point BottomLeft(this Rect rect)
        {
            return new Point(rect.Left, rect.Bottom);
        }

        public static Point Location(this Rect rect)
        {
            return rect.TopLeft();
        }

        public static Size Size(this Rect rect)
        {
            if (rect.IsEmpty)
                return System.Windows.Size.Empty;
            else
                return new Size(rect.Width, rect.Height);
        }
    }
}